#ifndef THREADPOOL_H
#define THREADPOOL_H

#include<list>
#include<cstdio>
#include<exception>
#include<pthread.h>
#include "../lock/locker.h"
#include "../CGImysql/sql_connection_pool.h"

template<typename T>
class threadpool{
public: 
    //thread_number是线程池中线程的数量
    threadpool(int actor_model,connection_pool *connPool,int thread_number=8,int max_request=10000);
    ~threadpool();
    //向请求队列中插入任务请求
    bool append(T *request,int state);
    bool append_p(T* request);
private:
    //工作线程运行的函数，不断从工作队列取出任务并执行
    static void *worker(void *arg);
    void run();
private:
    int m_thread_number;        //线程池中的线程数量
    int m_max_request;          //请求队列中允许的最大请求数
    pthread_t *m_threads;       //描述线程池的数组，大小为m_thread_number;
    std::list<T*> m_workqueue;  //请求队列
    locker m_queuelocker;       //请求队列的互斥锁
    sem m_queuestat;            //队列中任务的信号量
    connection_pool *m_connPool;//数据库
    int m_actor_model;          //模型切换
};
template<typename T>
threadpool<T>::threadpool(int actor_model,connection_pool *connPool,int thread_number=8,int max_request=10000){
    if(thread_number<=0||max_request<=0){
        //若线程数量或者最大请求数量不正确，则抛出异常
        throw std::exception();
    }
    m_threads=new pthread_t[m_thread_number];//创建线程块，并且用m_threads指向线程块数组
    if(!m_threads) throw std::exception(); //若创建失败，则抛出异常
    for(int i=0;i<thread_number;i++){
        if(pthread_create(m_thread+i,NULL,woker,this)!=0){//将线程标识符放入m_thread指向的空间，绑定工作函数以及工作函数的参数：线程池指针
            //若创建线程失败，则释放空间并抛出异常
            delete[] m_threads;
            throw std::exception();
        }
        if(pthread_detach(m_threads[i])){
            //将线程标记为可分离，分离后的线程在终止时自动释放资源，无需其他线程调用pthread_join
            delete[] m_threads;
            throw std::exception();
        }
    }
}

template<typename T>
threadpool<T>::~threadpool(){
    delete[] m_threads;
}

//插入请求队列,request是一个http连接对象的指针
template<typename T>
bool threadpool<T>::append(T* request,int state){
    m_queuelocker.lock();
    if(m_workqueue.size()>=m_max_request){
        m_queuelocker.unlock();
        return false;
    }
    request->m_state=state;
    m_workqueue.push_back(request);
    m_queuelocker.unlock();
    m_queuestat.post();
    return true;
}

template<typename T>
bool threadpool<T>::append_p(T* request){
    m_queuelocker.lock();
    if(m_workqueue.size()>=m_max_request){
        m_queuelocker.unlock();
        return false;
    }
    m_workqueue.push_back(request);
    m_queuelocker.unlock();
    m_queuestat.post();
    return true;
}

//worker函数，接受this指针，强转后调用run（）线程工作
template<typename T>
void *threadpool<T>::worker(void *arg){//void* 通用指针
    threadpool *pool=(threadpool*) arg;
    pool->run();
    return pool;
}

template<typename T>
void threadpool<T>::run(){
    while(true){
        m_queuestat.wait();
        m_queuelocker.lock();
        if(m_workqueue.empty()){
            m_queuelocker.unlock();
            continue;
        }
        T *request = m_workqueue.front();
        m_workqueue.pop_front();
        m_queuelocker.unlock();
        if(!request){
            continue;
        }
        //运行模式
        if(1==m_actor_model){
            //读写判断,0是读，1是写
            if(0==request->m_state){
                //read_once(),循环读取客户数据，直到无数据可读或对方关闭连接
                //非阻塞ET工作模式下，需要一次性将数据读完
                if(request->read_once()){
                    request->improv=1;
                    connectionRAII mysqlcon(&request->mysql,m_connPool);
                    request->process();
                    int
                    request->timer_flag=1;//定时器
                }
            }
        }
    }
}

#endif